package com.library.management.entity;

import com.library.management.enums.BookStatus;
import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 图书实体类
 * 核心业务实体，管理图书馆所有图书信息
 *
 * 关联关系：
 * - 多对一：图书分类
 * - 一对多：借阅记录、预约记录
 *
 * 业务功能：
 * - 图书信息管理
 * - 库存管理
 * - 借阅状态跟踪
 *
 * @author 开发者
 * @version 1.0
 * @since 2025-10-19
 */
@Entity
@Table(name = "books", indexes = {
        @Index(name = "idx_books_isbn", columnList = "isbn"),
        @Index(name = "idx_books_title", columnList = "title"),
        @Index(name = "idx_books_author", columnList = "author"),
        @Index(name = "idx_books_publisher", columnList = "publisher"),
        @Index(name = "idx_books_category_id", columnList = "category_id"),
        @Index(name = "idx_books_status", columnList = "status"),
        @Index(name = "idx_books_publish_year", columnList = "publish_year")
})
@Data
@EqualsAndHashCode(exclude = {"category", "borrowRecords", "reservations"})
@ToString(exclude = {"category", "borrowRecords", "reservations"})
public class Book {

    // ========== 主键标识 ==========

    /**
     * 图书ID - 主键，自增长
     * 数据库字段：id (BIGINT, PRIMARY KEY, AUTO_INCREMENT)
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // ========== 图书标识信息 ==========

    /**
     * ISBN号 - 国际标准书号，唯一标识
     * 数据库字段：isbn (VARCHAR(20), UNIQUE, NOT NULL)
     */
    @Column(unique = true, nullable = false, length = 20)
    private String isbn;

    /**
     * 书名 - 图书名称
     * 数据库字段：title (VARCHAR(200), NOT NULL)
     */
    @Column(nullable = false, length = 200)
    private String title;

    /**
     * 副标题 - 图书副标题
     * 数据库字段：subtitle (VARCHAR(200))
     */
    @Column(length = 200)
    private String subtitle;

    /**
     * 作者 - 图书作者
     * 数据库字段：author (VARCHAR(100), NOT NULL)
     */
    @Column(nullable = false, length = 100)
    private String author;

    /**
     * 译者 - 图书译者（如果是翻译作品）
     * 数据库字段：translator (VARCHAR(100))
     */
    @Column(length = 100)
    private String translator;

    /**
     * 出版社 - 出版单位
     * 数据库字段：publisher (VARCHAR(100), NOT NULL)
     */
    @Column(nullable = false, length = 100)
    private String publisher;

    /**
     * 出版日期 - 具体出版日期
     * 数据库字段：publish_date (DATE)
     */
    @Column(name = "publish_date")
    private LocalDate publishDate;

    /**
     * 出版年份 - 出版年份，用于快速查询
     * 数据库字段：publish_year (INT)
     */
    @Column(name = "publish_year")
    private Integer publishYear;

    // ========== 分类关联关系 ==========

    /**
     * 图书分类 - 图书所属分类
     * 多对一关系，外键关联book_categories表
     * 延迟加载提高性能
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id", nullable = false, foreignKey = @ForeignKey(name = "fk_books_category_id"))
    private BookCategory category;

    // ========== 图书详情信息 ==========

    /**
     * 版次信息 - 图书版次
     * 数据库字段：edition (VARCHAR(50))
     */
    @Column(length = 50)
    private String edition;

    /**
     * 页数 - 图书总页数
     * 数据库字段：page_count (INT)
     */
    @Column(name = "page_count")
    private Integer pageCount;

    /**
     * 语言 - 图书语言，默认中文
     * 数据库字段：language (VARCHAR(20)), DEFAULT '中文'
     */
    @Column(length = 20)
    private String language = "中文";

    /**
     * 价格 - 图书定价
     * 数据库字段：price (DECIMAL(10,2))
     */
    @Column(precision = 10, scale = 2)
    private BigDecimal price;

    /**
     * 封面图片URL - 图书封面图片地址
     * 数据库字段：cover_image (VARCHAR(200))
     */
    @Column(name = "cover_image", length = 200)
    private String coverImage;

    /**
     * 内容简介 - 图书内容摘要
     * 数据库字段：summary (TEXT)
     */
    @Column(columnDefinition = "TEXT")
    private String summary;

    // ========== 库存管理信息 ==========

    /**
     * 总册数 - 该图书的总库存数量
     * 数据库字段：total_copies (INT), DEFAULT 1
     */
    @Column(name = "total_copies")
    private Integer totalCopies = 1;

    /**
     * 可借册数 - 当前可借阅的数量
     * 数据库字段：available_copies (INT), DEFAULT 1
     */
    @Column(name = "available_copies")
    private Integer availableCopies = 1;

    /**
     * 馆藏位置 - 图书在图书馆中的具体位置
     * 数据库字段：location (VARCHAR(100))
     */
    @Column(length = 100)
    private String location;

    /**
     * 图书状态 - 当前图书状态
     * AVAILABLE: 可借阅，BORROWED: 已借出，RESERVED: 已预约，MAINTENANCE: 维护中，LOST: 已遗失
     * 数据库字段：status (ENUM), NOT NULL
     */
    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 20)
    private BookStatus status = BookStatus.AVAILABLE;

    // ========== 关联关系 ==========

    /**
     * 借阅记录列表 - 该图书的所有借阅历史
     * 一对多关系，级联操作：所有操作
     * 延迟加载提高性能
     */
    @OneToMany(mappedBy = "book", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<BorrowRecord> borrowRecords = new ArrayList<>();

    /**
     * 预约记录列表 - 该图书的所有预约记录
     * 一对多关系，级联操作：所有操作
     */
    @OneToMany(mappedBy = "book", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Reservation> reservations = new ArrayList<>();

    // ========== 审计字段 ==========

    /**
     * 创建人ID - 记录创建者
     * 数据库字段：created_by (BIGINT)
     */
    @Column(name = "created_by")
    private Long createdBy;

    /**
     * 更新人ID - 记录最后修改者
     * 数据库字段：updated_by (BIGINT)
     */
    @Column(name = "updated_by")
    private Long updatedBy;

    /**
     * 创建时间 - 记录创建时间，自动生成
     * 数据库字段：created_time (DATETIME), DEFAULT CURRENT_TIMESTAMP
     */
    @CreationTimestamp
    @Column(name = "created_time", updatable = false)
    private LocalDateTime createdTime;

    /**
     * 更新时间 - 记录最后修改时间，自动更新
     * 数据库字段：updated_time (DATETIME), DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
     */
    @UpdateTimestamp
    @Column(name = "updated_time")
    private LocalDateTime updatedTime;

    // ========== 业务方法 ==========

    /**
     * 检查图书是否可借
     * 验证条件：图书状态为可借阅，且可借册数大于0
     *
     * @return true-可借，false-不可借
     */
    public boolean isAvailableForBorrow() {
        return this.status == BookStatus.AVAILABLE && this.availableCopies > 0;
    }

    /**
     * 借出图书
     * 减少可借册数，如果可借册数为0则更新状态为已借出
     *
     * @return true-借出成功，false-借出失败
     */
    public boolean borrowBook() {
        if (isAvailableForBorrow()) {
            this.availableCopies--;
            if (this.availableCopies == 0) {
                this.status = BookStatus.BORROWED;
            }
            return true;
        }
        return false;
    }

    /**
     * 归还图书
     * 增加可借册数，如果状态为已借出且可借册数大于0则更新状态为可借阅
     *
     * @return true-归还成功，false-归还失败
     */
    public boolean returnBook() {
        if (this.availableCopies < this.totalCopies) {
            this.availableCopies++;
            if (this.status == BookStatus.BORROWED && this.availableCopies > 0) {
                this.status = BookStatus.AVAILABLE;
            }
            return true;
        }
        return false;
    }

    /**
     * 获取借阅次数
     * 统计该图书的总借阅次数
     *
     * @return 借阅总次数
     */
    public long getBorrowCount() {
        return this.borrowRecords != null ? this.borrowRecords.size() : 0;
    }

    /**
     * 获取当前借出数量
     * 计算当前被借出的图书数量
     *
     * @return 当前借出数量
     */
    public int getBorrowedCount() {
        return this.totalCopies - this.availableCopies;
    }

    /**
     * 检查图书是否有预约
     *
     * @return true-有预约，false-无预约
     */
    public boolean hasReservations() {
        return this.reservations != null && !this.reservations.isEmpty();
    }

    /**
     * 获取活跃预约数量
     * 统计状态为PENDING的预约数量
     *
     * @return 活跃预约数量
     */
    public long getActiveReservationCount() {
        if (this.reservations == null) {
            return 0;
        }
        return this.reservations.stream()
                .filter(reservation -> "PENDING".equals(reservation.getStatus()))
                .count();
    }
}